package uestc.lj.gulishop.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import uestc.lj.common.constant.AuthServerConstant;
import uestc.lj.common.to.SocialUser;
import uestc.lj.common.utils.HttpUtils;
import uestc.lj.common.utils.R;
import uestc.lj.gulishop.auth.feign.MemberFeignService;
import uestc.lj.gulishop.auth.feign.MessageFeginService;
import uestc.lj.gulishop.auth.service.LoginService;
import uestc.lj.common.vo.MemberResponseVO;
import uestc.lj.gulishop.auth.vo.UserLoginVO;
import uestc.lj.gulishop.auth.vo.UserRegistVO;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author:Crazlee
 * @Date:2021/6/10
 */
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private MessageFeginService messageFeginService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MemberFeignService memberFeignService;

    @Override
    public boolean sendCode(String phone) {
        // TODO 接口防刷

        // 3.防止同一个手机号在60s内再次发送验证码
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone);
        if (!StringUtils.isEmpty(redisCode)) {
            long agoTime = Long.parseLong(redisCode.split("_")[1]);
            long currentTime = System.currentTimeMillis();
            if (currentTime - agoTime < 60 * 1000) {
                return false;
            }
        }
        // 1.生成6位验证码
        String code = UUID.randomUUID().toString().substring(0, 6) + "_" + System.currentTimeMillis();
        // 2.保存至redis
        stringRedisTemplate.opsForValue().set(AuthServerConstant.SMS_CODE_CACHE_PREFIX + phone, code, 5, TimeUnit.MINUTES);
        code = code.split("_")[0];
        messageFeginService.sendCode(phone, code);
        return true;
    }

    @Override
    public boolean regist(UserRegistVO userRegistVO, BindingResult result, RedirectAttributes redirectAttributes) {
        // 1.校验出错，封装错误信息，返回注册页面
        if (result.hasErrors()) {
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField,
                    FieldError::getDefaultMessage));
            redirectAttributes.addFlashAttribute("errors", errors);
            return false;
        }
        // 2.核对验证码是否正确
        String code = userRegistVO.getCode();
        String redisCode = stringRedisTemplate.opsForValue().get(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userRegistVO.getPhone());
        if (!StringUtils.isEmpty(redisCode)) {
            // 判断redis验证码是否过期
            if (code.equals(redisCode.split("_")[0])) {
                // 验证码校验正确，删除旧的验证码
                stringRedisTemplate.delete(AuthServerConstant.SMS_CODE_CACHE_PREFIX + userRegistVO.getPhone());
                // 2.校验成功，执行注册方法
                R r = memberFeignService.regist(userRegistVO);
                if (r.getCode() == 0) {
                    // 注册成功
                    return true;
                } else {
                    HashMap<String, String> errors = new HashMap<>();
                    errors.put("msg", String.valueOf(r.get("msg")));
                    redirectAttributes.addFlashAttribute("errors", errors);
                    return false;
                }
            } else {
                HashMap<String, String> errors = new HashMap<>();
                errors.put("code", "验证码错误");
                redirectAttributes.addFlashAttribute("errors", errors);
                return false;
            }
        } else {
            HashMap<String, String> errors = new HashMap<>();
            errors.put("code", "验证码已过期，请重新点击发送");
            redirectAttributes.addFlashAttribute("errors", errors);
            return false;
        }
    }

    @Override
    public boolean login(UserLoginVO userLoginVO, RedirectAttributes redirectAttributes, HttpSession session) {

        R r = memberFeignService.login(userLoginVO);
        if (r.getCode() == 0) {
            MemberResponseVO memberResponseVO = r.getData("data", new TypeReference<MemberResponseVO>() {
            });
            session.setAttribute(AuthServerConstant.LOGIN_USER, memberResponseVO);
            return true;
        } else {
            HashMap<String, String> errors = new HashMap<>();
            errors.put("msg", String.valueOf(r.get("msg")));
            redirectAttributes.addFlashAttribute("errors", errors);
            return false;
        }
    }

    @Override
    public boolean weiboLogin(String code, HttpSession session, HttpServletResponse httpResponse) throws Exception {
        // 根据code换取accesstoken
        Map<String, String> map = new HashMap<>();
        map.put("client_id", "2636917288");
        map.put("client_secret", "61496841565645156");
        map.put("grant_type", "authorization_code");
        map.put("redirecr_uri", "http://gulishop.com/oauth2.0/weibo/success");
        map.put("code", code);

        HttpResponse response = HttpUtils.doPost("api.weibo.com", "/oauth2/access_token", "post", null, null, map);

        if (response.getStatusLine().getStatusCode() == 200) {
            //获取到accesstoken
            String json = EntityUtils.toString(response.getEntity());
            SocialUser socialUser = JSON.parseObject(json, SocialUser.class);
            // 若用户是第一次进网站则需要自动注册
            R r = memberFeignService.weiboLogin(socialUser);
            if (r.getCode() == 0) {
                MemberResponseVO memberResponseVO = r.getData("data", new TypeReference<MemberResponseVO>() {
                });
                // 查询成功，放入session
                session.setAttribute("loginUser", memberResponseVO);
                return true;
            } else {
                return false;
            }
        }
        return false;
    }
}
